﻿using Johnny;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Drawing;
using System.IO;

// How to do this unit test:

// Simply press F5 to begin tests.
// Do not modify the xml files under either bin/Debug or bin/Release. They will always be overriden.
// Instead, edit the files under TestData folder in Visual Studio.

namespace UnitTests
{   
    /// <summary>
    ///這是 AltColorConverterTest 的測試類別，應該包含所有 AltColorConverterTest 單元測試
    ///</summary>
    [TestClass()]
    public class AltColorConverterTest
    {
        /// <summary>
        ///取得或設定提供目前測試回合的相關資訊與功能的測試內容。
        ///</summary>
        public TestContext TestContext { get; set; }

        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {
            // Copy all test data files to where the tests can access. In this way you can edit the xml files right under Visual Studio.
            deployTestFiles(); 
        }

        //在執行類別中的所有測試之後，使用 ClassCleanup 執行程式碼
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //在執行每一項測試之前，先使用 TestInitialize 執行程式碼
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //在執行每一項測試之後，使用 TestCleanup 執行程式碼
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}

#region Test ConvertFromString

        /// <summary>
        /// Test ConvertFromString - Type 1
        /// </summary>
        [
        DeploymentItem("UnitTests\\TestData\\ConvertFromStringTestType1.xml"),
        DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\ConvertFromStringTestType1.xml", "Data", DataAccessMethod.Sequential), 
        TestMethod()]
        public void ConvertFromStringTestType1()
        {
            ConvertFromStringTest(TestContext);
        }

        /// <summary>
        /// Test ConvertFromString - Type 2
        /// </summary>
        [DeploymentItem("UnitTests\\TestData\\ConvertFromStringTestType2.xml"), 
        DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\ConvertFromStringTestType2.xml", "Data", DataAccessMethod.Sequential), 
        TestMethod()]
        public void ConvertFromStringTestType2()
        {
            ConvertFromStringTest(TestContext);
        }

        /// <summary>
        /// Test ConvertFromString - Type 3
        /// </summary>
        [DeploymentItem("UnitTests\\TestData\\ConvertFromStringTestType3.xml"), 
        DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\ConvertFromStringTestType3.xml", "Data", DataAccessMethod.Sequential), 
        TestMethod()]
        public void ConvertFromStringTestType3()
        {
            ConvertFromStringTest(TestContext);
        }

        /// <summary>
        /// Test ConvertFromString - Type 4
        /// </summary>
        [DeploymentItem("UnitTests\\TestData\\ConvertFromStringTestType4.xml"), 
        DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\ConvertFromStringTestType4.xml", "Data", DataAccessMethod.Sequential), 
        TestMethod()]
        public void ConvertFromStringTestType4()
        {
            ConvertFromStringTest(TestContext);
        }

        /// <summary>
        /// Test ConvertFromString - Type 5
        /// </summary>
        [DeploymentItem("UnitTests\\TestData\\ConvertFromStringTestType5.xml"),
        DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\ConvertFromStringTestType5.xml", "Data", DataAccessMethod.Sequential),
        TestMethod()]
        public void ConvertFromStringTestType5()
        {
            ConvertFromStringTest(TestContext);
        }


#region Private methods

        /// <summary>
        /// Copy test data files under the TestData folder to where the executable resides.
        /// </summary>
        private static void deployTestFiles()
        {
            string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
            string testDataDirectory = baseDirectory.Replace("\\bin\\Debug", "").Replace("\\bin\\Release", "") + "\\TestData";
            string[] files = Directory.GetFiles(testDataDirectory, "*.xml");
            foreach (string file in files)
                deploy(file, file.Replace(testDataDirectory + "\\", ""), baseDirectory);
        }

        /// <summary>
        /// Deploy every single test data file to where the executable resides
        /// </summary>
        private static void deploy(string sourcePath, string fileName, string destination)
        {
            File.Copy(sourcePath, destination + "\\" + fileName, true);
        }

        /// <summary>
        /// The common test logic of ConvertFromString() for different types of data
        /// </summary>
        private void ConvertFromStringTest(TestContext context)
        {
            string input = (string)context.DataRow["Input"];
            string expected = (string)context.DataRow["Expected"];
            string result = (string)context.DataRow["Result"];
            Color actualColor = AltColorConverter.ConvertFromString(input);
            Color expectedColor = convertStrToColor(expected);
            bool isMatch = result == "1";
            Assert.AreEqual(compareColor(expectedColor, actualColor), isMatch);
        }

        /// <summary>
        /// Compare 2 colors to see if they are the same color, even if they have different names
        /// </summary>
        /// <remarks>
        /// This compare is to compensate situations where Color.FromARGB() may create color with names 
        /// like {Name="FFFFFFFFFFFF", ARGB={0,0,0,0}}. This way, it'll be unequal to an identical color
        /// with another name (like {Name="0", ARGB={0,0,0,0}}).
        /// </remarks>
        private bool compareColor(Color expected, Color actual)
        {
            return (actual.A == expected.A &&
                actual.R == expected.R &&
                actual.G == expected.G &&
                actual.B == expected.B);
        }

        /// <summary>
        /// Convert the input string (in "A, R, G, B" formmat) to Color
        /// </summary>
        /// <param name="expectedStr">Must be in "A, R, G, B" formmat</param>
        private Color convertStrToColor(string expectedStr)
        {
            try
            {
                string[] values = expectedStr.Split(',');
                int a, r, g, b;
                if (int.TryParse(values[0], out a) &&
                    int.TryParse(values[1], out r) &&
                    int.TryParse(values[2], out g) &&
                    int.TryParse(values[3], out b))
                    return Color.FromArgb(a, r, g, b);
                else
                    Assert.Inconclusive("convertStrToColor() error: input \"{0}\" not correct!", expectedStr);
            }
            catch (Exception ex)
            {
                Assert.Inconclusive("convertStrToColor() error: input \"{0}\" may be incorrect! Exception message: {1}", expectedStr, ex.Message);
            }
            return Color.Black;
        }

#endregion

#endregion

        /// <summary>
        /// Test convertDecValue
        ///</summary>
        [DeploymentItem("AltColerConverter.dll"), DeploymentItem("UnitTests\\TestData\\frameDecValueTest.xml"),
        DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\frameDecValueTest.xml", "Data", DataAccessMethod.Sequential),
        TestMethod()]
        public void frameDecValueTest()
        {
            string input = (string)TestContext.DataRow["Input"];
            string expected = (string)TestContext.DataRow["Expected"];
            string result = (string)TestContext.DataRow["Result"];
            int actual = AltColorConverter_Accessor.frameDecValue(input);
            int expectedInt = int.Parse(expected);
            bool isMatch = result == "1";
            Assert.AreEqual((expectedInt == actual), isMatch);
        }


        /// <summary>
        /// Test convertHexValue
        ///</summary>
        [DeploymentItem("AltColerConverter.dll"), DeploymentItem("UnitTests\\TestData\\convertHexValueTest.xml"),
        DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\convertHexValueTest.xml", "Data", DataAccessMethod.Sequential),
        TestMethod()]
        public void convertHexValueTest()
        {
            string input = (string)TestContext.DataRow["Input"];
            string expected = (string)TestContext.DataRow["Expected"];
            string result = (string)TestContext.DataRow["Result"];
            int actual = AltColorConverter_Accessor.convertHexValue(input);
            int expectedInt = int.Parse(expected);
            bool isMatch = result == "1";
            Assert.AreEqual((expectedInt == actual), isMatch);
        }

        /// <summary>
        /// Test convertHexValue
        ///</summary>
        [DeploymentItem("AltColerConverter.dll"), DeploymentItem("UnitTests\\TestData\\convertShortHexValueTest.xml"),
        DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\convertShortHexValueTest.xml", "Data", DataAccessMethod.Sequential),
        TestMethod()]
        public void convertShortHexValueTest()
        {
            string input = (string)TestContext.DataRow["Input"];
            string expected = (string)TestContext.DataRow["Expected"];
            string result = (string)TestContext.DataRow["Result"];
            int actual = AltColorConverter_Accessor.convertShortHexValue(input);
            int expectedInt = int.Parse(expected);
            bool isMatch = result == "1";
            Assert.AreEqual((expectedInt == actual), isMatch);        
        }

    }
}
